package com.gillion.grule.client.utils;


import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.gillion.grule.client.exception.SystemRuntimeException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EntityUtils {
    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    private static final Logger LOGGER = LoggerFactory.getLogger(EntityUtils.class);

    static {
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        OBJECT_MAPPER.setDateFormat((DateFormat)new ISO8601DateFormat());
    }

    public static <T> T map2Bean(Map<String, Object> map, Class<T> clazz) {
        try {
            String json = OBJECT_MAPPER.writeValueAsString(map);
            return (T)OBJECT_MAPPER.readValue(json, clazz);
        } catch (Exception e) {
            LOGGER.error("map转换失败" , e);
            return null;
        }
    }

    public static <T> T object2Bean(Object o, Class<T> clazz) {
        try {
            String jsonStr = OBJECT_MAPPER.writeValueAsString(o);
            return (T)OBJECT_MAPPER.readValue(jsonStr, clazz);
        } catch (IOException e) {
            LOGGER.error("对象转换失败", e);
            throw new SystemRuntimeException(e.getMessage());
        }
    }

    public static String toJSONString(Object object) {
        if (object != null)
            try {
                return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(object);
            } catch (JsonProcessingException e) {
                LOGGER.error("JSON字符串转换失败", (Throwable)e);
                throw new SystemRuntimeException(e.getMessage());
            }
        return "";
    }

    public static byte[] toJSONByte(Object object) {
        if (object != null)
            try {
                return OBJECT_MAPPER.writeValueAsBytes(object);
            } catch (JsonProcessingException e) {
                LOGGER.error("对象序列化失败",e);
                throw new SystemRuntimeException(e.getMessage());
            }
        return new byte[0];
    }

    public static <T> List<T> list2Beans(List<Object> list, Class<?> clazz) {
        List<T> rtnList = Lists.newArrayList();
        try {
            for (Object object : list) {
                String json = OBJECT_MAPPER.writeValueAsString(object);
                Object result = OBJECT_MAPPER.readValue(json, clazz);
                rtnList.add((T)result);
            }
        } catch (Exception e) {
            LOGGER.error("List转换失败" , e);
            throw new SystemRuntimeException(e.getMessage());
        }
        return rtnList;
    }

    public static Map<String, Object> map2Beans(Map<String, Object> map, Map<String, Class<?>> settings) {
        Map<String, Object> rtnValue = Maps.newHashMap();
        Iterator<String> it = settings.keySet().iterator();
        while (it.hasNext()) {
            String name = it.next();
            Object obj = map.get(name);
            if (obj == null) {
                rtnValue.put(name, null);
                continue;
            }
            Class<?> clazz = settings.get(name);
            if (obj instanceof Map) {
                Object value = map2Bean((Map<String, Object>)obj, clazz);
                rtnValue.put(name, value);
                continue;
            }
            if (obj instanceof List) {
                List<Object> value = list2Beans((List)obj, clazz);
                rtnValue.put(name, value);
                continue;
            }
            if (obj.getClass().equals(clazz))
                rtnValue.put(name, map.get(name));
        }
        return rtnValue;
    }

    public static <T> T readObjectFromJSONString(String str, Class<T> clazz) {
        return StringUtils.isEmpty(str) ? null : readObject(str.getBytes(), clazz);
    }

    public static <T> T readObject(byte[] data, Class<T> clazz) {
        JavaType javaType = OBJECT_MAPPER.constructType(clazz);
        try {
            return (T)OBJECT_MAPPER.readValue(data, javaType);
        } catch (IOException e) {
            throw new SystemRuntimeException(e.getMessage());
        }
    }

    public static <T> T readObject(InputStream data, Class<T> clazz) {
        JavaType javaType = OBJECT_MAPPER.constructType(clazz);
        try {
            return (T)OBJECT_MAPPER.readValue(data, javaType);
        } catch (IOException e) {
            throw new SystemRuntimeException(e.getMessage());
        }
    }
}
